using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Web;
using System.Collections;
using System.Web.Script.Services;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.ComponentModel;
using Dzzzr;

namespace MonitoringService
{
	/// <summary>
	/// Summary description for DzzzrPointingService
	/// </summary>
	[WebService(Namespace = "http://tempuri.org/")]
	[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
	[ToolboxItem(false)]
  public class DzzzrPointingService : System.Web.Services.WebService
	{

		/// <summary>
		/// Return connection to SQL server
		/// </summary>
		/// <returns></returns>
		protected SqlConnection GetConnection()
		{
			string connectionString = ConfigurationManager.ConnectionStrings["SqlServer"].ConnectionString;
			SqlConnection connection = new SqlConnection(connectionString);
			return connection;
		}

		/// <summary>
		/// Get command for insert point
		/// </summary>
		/// <param name="login"></param>
		/// <param name="password"></param>
		/// <param name="markerName"></param>
		/// <param name="gameName"></param>
		/// <param name="latitude"></param>
		/// <param name="longitude"></param>
		private SqlCommand GetPointCommand(string login, string password, string markerName, string gameName, float latitude, float longitude)
		{
			SqlConnection connection = GetConnection();
			SqlCommand command = new SqlCommand("AddPoint", connection);
			command.CommandType = CommandType.StoredProcedure;
			command.Parameters.Add(new SqlParameter("@login", login));
			command.Parameters.Add(new SqlParameter("@password", password));
			command.Parameters.Add(new SqlParameter("@markerName", markerName));
			command.Parameters.Add(new SqlParameter("@gameName", gameName));
			command.Parameters.Add(new SqlParameter("@latitude", latitude));
			command.Parameters.Add(new SqlParameter("@longitude", longitude));
			return command;
		}

		/// <summary>
		/// Class for auto open and close connection
		/// </summary>
		class AutoOpenCloseConnection : IDisposable
		{
			/// <summary>
			/// SQL command for execute
			/// </summary>
			SqlCommand command = null;

			/// <summary>
			/// Constructor
			/// </summary>
			/// <param name="command"></param>
			public AutoOpenCloseConnection(SqlCommand command)
			{
				// save command
				this.command = command;
				// open connection
				if (this.command != null && this.command.Connection != null)
					this.command.Connection.Open();
			}
      public void ExecuteNonQuery()
      {
        
      }

			/// <summary>
			/// Free resources
			/// </summary>
			public void Dispose()
			{
				// close connection
				if (this.command != null && this.command.Connection != null)
					this.command.Connection.Close();
			}
		}

		#region IDzzrPointingService Members

		/// <summary>
		/// Add point from <see cref="Marker"/>
		/// </summary>
		/// <param name="login">Person login</param>
		/// <param name="password">Person password</param>
		/// <param name="markerName">Marker name</param>
		/// <param name="gameName">Game name</param>
		/// <param name="latitude">Point latitude</param>
		/// <param name="longitude">Point logitude</param>
		[WebMethod]
		public void AddPoint(string login, string password, string markerName, string gameName, float latitude, float longitude)
		{
			SqlCommand command = GetPointCommand(login, password, markerName, gameName, latitude, longitude);
			using (new AutoOpenCloseConnection(command))
			{
				int rowAffected = command.ExecuteNonQuery();
				if (rowAffected == 0)
					throw new ApplicationException("Error adding point");
			}
		}

		/// <summary>
		/// Add point from <see cref="Marker"/>
		/// </summary>
		/// <param name="login"><see cref="Person"/> login</param>
		/// <param name="password"><see cref="Person"/> password</param>
		/// <param name="markerName"><see cref="Marker"/> name</param>
		/// <param name="gameName"><see cref="Game"/> name</param>
		/// <param name="latitude">Point latitude</param>
		/// <param name="longitude">Point logitude</param>
		/// <param name="altitude">Point altitude</param>
		/// <param name="speed">Point speed</param>
		[WebMethod]
		public void AddPoint2(string login, string password, string markerName, string gameName, float latitude, float longitude, float altitude, int speed)
		{
			SqlCommand command = GetPointCommand(login, password, markerName, gameName, latitude, longitude);
			command.Parameters.Add(new SqlParameter("@altitude", altitude));
			command.Parameters.Add(new SqlParameter("@speed", speed));
			using (new AutoOpenCloseConnection(command))
			{
				int rowAffected = command.ExecuteNonQuery();
				if (rowAffected == 0)
					throw new ApplicationException("Error adding point");
			}
		}

		/// <summary>
		/// Login and request hash value for performance issue
		/// </summary>
		/// <param name="markerName">Marker name</param>
		/// <param name="gameName">Game name</param>
		/// <param name="login">Person login</param>
		/// <param name="password">Person password</param>
		[WebMethod]
		public DateTime MarkerLogin(string markerName, string gameName, string login, string password)
		{
			SqlConnection connection = GetConnection();
			SqlCommand command = new SqlCommand("MarkerLogin", connection);
			command.CommandType = CommandType.StoredProcedure;
			command.Parameters.Add(new SqlParameter("@login", login));
			command.Parameters.Add(new SqlParameter("@password", password));
			command.Parameters.Add(new SqlParameter("@markerName", markerName));
			command.Parameters.Add(new SqlParameter("@gameName", gameName));
			using (new AutoOpenCloseConnection(command))
			{
				object result = command.ExecuteScalar();
				if (result is DateTime)
					return (DateTime)result;
				else
					throw new ApplicationException("Error adding point");
			}
		}

		/// <summary>
		/// Add point from <see cref="Marker"/> using hash value
		/// </summary>
		/// <param name="hash">Hash value from <see cref="MarkerLogin"/></param>
		/// <param name="latitude">Point latitude</param>
		/// <param name="longitude">Point logitude</param>
		[WebMethod]
		public void AddPointHashed(DateTime hash, float latitude, float longitude)
		{
			SqlConnection connection = GetConnection();
			SqlCommand command = new SqlCommand("AddPointHashed", connection);
			command.CommandType = CommandType.StoredProcedure;
			command.Parameters.Add(new SqlParameter("@hash", hash));
			command.Parameters.Add(new SqlParameter("@latitude", latitude));
			command.Parameters.Add(new SqlParameter("@longitude", longitude));
			using (new AutoOpenCloseConnection(command))
			{
				int rowAffected = command.ExecuteNonQuery();
				if (rowAffected == 0)
					throw new ApplicationException("Error adding point");
			}
		}

		/// <summary>
		/// Add point from <see cref="Marker"/> using hash value
		/// </summary>
		/// <param name="hash">Hash value from <see cref="MarkerLogin"/></param>
		/// <param name="latitude">Point latitude</param>
		/// <param name="longitude">Point logitude</param>
		/// <param name="altitude">Point altitude</param>
		/// <param name="speed">Point speed</param>
		[WebMethod]
		public void AddPointHashed2(DateTime hash, float latitude, float longitude, float altitude, int speed)
		{
			SqlConnection connection = GetConnection();
			SqlCommand command = new SqlCommand("AddPointHashed", connection);
			command.CommandType = CommandType.StoredProcedure;
			command.Parameters.Add(new SqlParameter("@hash", hash));
			command.Parameters.Add(new SqlParameter("@latitude", latitude));
			command.Parameters.Add(new SqlParameter("@longitude", longitude));
			command.Parameters.Add(new SqlParameter("@altitude", altitude));
			command.Parameters.Add(new SqlParameter("@speed", speed));
			using (new AutoOpenCloseConnection(command))
			{
				int rowAffected = command.ExecuteNonQuery();
				if (rowAffected == 0)
					throw new ApplicationException("Error adding point");
			}
		}

		#endregion

	  /// <summary>
	  /// Get last markers positions by game name
	  /// </summary>
	  /// <param name="gameName"></param>
	  /// <param name="login"></param>
	  /// <param name="password"></param>
	  /// <returns></returns>
	  [WebMethod]
	  public List<SimpleMarker> GetMarkers(string gameName, string login, string password)
	  {
	    SqlConnection connection = GetConnection();
	    SqlCommand command = new SqlCommand("GetMarkers", connection);
	    command.CommandType = CommandType.StoredProcedure;
	    command.Parameters.Add(new SqlParameter("@gameName", gameName));
      command.Parameters.Add(new SqlParameter("@login", login));
	    command.Parameters.Add(new SqlParameter("@password", password));
      List<SimpleMarker> result = new List<SimpleMarker>();
	    connection.Open();
	    using (SqlDataReader rd = command.ExecuteReader(CommandBehavior.CloseConnection))
	    {
	      while (rd.Read())//repeat for all rows
	      {
	        result.Add(//Add new simple marker from reader
            new SimpleMarker(rd.GetString(0), rd.GetString(1), (float)rd.GetDouble(2), (float)rd.GetDouble(3),
	                           rd.IsDBNull(4) ? (float?) null : (float)rd.GetDouble(4),
	                           rd.IsDBNull(5) ? (int?) null :  Convert.ToInt32(rd.GetDouble(5)),
                             rd.GetInt32(6)));
	      }
	    }
	    return result;
  	}
	}
}
